package com.panfeng.xcloud.scheduler.service.impl;

import com.panfeng.xcloud.common.core.constants.BlConstants;
import com.panfeng.xcloud.common.core.enums.AddressTypeEnum;
import com.panfeng.xcloud.common.core.enums.ChainTypeEnum;
import com.panfeng.xcloud.common.core.enums.CoinTypeEnum;
import com.panfeng.xcloud.common.core.enums.RechargeLogTypeEnum;
import com.panfeng.xcloud.common.core.utils.DES3Util;
import com.panfeng.xcloud.common.core.utils.StringUtils;
import com.panfeng.xcloud.dao.assets.entity.RechargeLog;
import com.panfeng.xcloud.dao.assets.entity.UserWalletInfo;
import com.panfeng.xcloud.scheduler.dao.mapper.RechargeLogMapperExt;
import com.panfeng.xcloud.scheduler.dao.mapper.UserWalletInfoMapperExt;
import com.panfeng.xcloud.scheduler.dto.request.RechargeLogReqDTO;
import com.panfeng.xcloud.scheduler.service.ICollectTronUsdtService;
import com.panfeng.xcloud.scheduler.service.IFeignService;
import com.panfeng.xcloud.scheduler.util.tron.TransactionResult;
import com.panfeng.xcloud.scheduler.util.tron.Trc20Helper;
import com.panfeng.xcloud.scheduler.util.tron.TrxHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class CollectTronUsdtServiceImpl implements ICollectTronUsdtService {

    @Autowired
    private RechargeLogMapperExt rechargeLogMapperExt;

    @Autowired
    private UserWalletInfoMapperExt userWalletInfoMapperExt;

    @Autowired
    private TronTrc20Service tronTrc20Service;

    @Value("${xdcloud.des3.secret-key}")
    private String secrectKey;

    @Autowired
    @Qualifier(value = "notLoadBalancedRestTemplate")
    private RestTemplate restTemplate;

    @Autowired
    private IFeignService feignService;

    /**
     * TRC20 USDT归集定时任务
     */
    @Override
    public void collectTronUsdt() {
        BigDecimal fee = BlConstants.TRC20_FEE;    //用于归集的燃料费
        RechargeLogReqDTO rechargeLogReqDTO = new RechargeLogReqDTO();
        rechargeLogReqDTO.setChainName(ChainTypeEnum.TRON.getCode());
        rechargeLogReqDTO.setCoinName(CoinTypeEnum.USDT.getCode());
        rechargeLogReqDTO.setState(RechargeLogTypeEnum.RECHARGE_SUCCESS.getCode());
        rechargeLogReqDTO.setLimit(100);
        List<RechargeLog> rechargeList = rechargeLogMapperExt.selectRechargeList(rechargeLogReqDTO);
        if (rechargeList == null || rechargeList.size() == 0) {
            return;
        }

        log.info("开始归集，共{}比交易", rechargeList.size());
        String outPrivateKey = "";
        String inAddress = "";
        String contractAddress = "";
        for (RechargeLog logEntity : rechargeList) {
            try {
                UserWalletInfo userCoin = userWalletInfoMapperExt.getUserWalletInfoByAddress(logEntity.getChainName(), logEntity.getCoinName(), logEntity.getToAddress());
                if (userCoin == null) {
                    log.info(logEntity.getCoinName() + "~~~~~~~~~~", logEntity.getToAddress());
                    continue;
                }

                if (userCoin.getCoinName().equals(CoinTypeEnum.USDT.getCode())) {
                    contractAddress = BlConstants.UsdtContractAddress;
                }

                UserWalletInfo inUserWalletInfo = new UserWalletInfo();
                inUserWalletInfo.setChainName(logEntity.getChainName());
                inUserWalletInfo.setCoinName(logEntity.getCoinName());
                inUserWalletInfo.setUserId(AddressTypeEnum.COLLECT.getCode());
                UserWalletInfo in = userWalletInfoMapperExt.selectOne(inUserWalletInfo);
                inAddress = in.getAddress();

                if (userCoin.getAddress().equals(inAddress)) {
                    continue;
                }

                if (inAddress == null) {
                    log.error("归集未配置入账地址");
                    return;
                }

                outPrivateKey = DES3Util.doubleDecode(userCoin.getPrivateKey(), secrectKey, userCoin.getSalt());

                if (!Trc20Helper.hasTrxFee(userCoin.getAddress(), restTemplate)) {
                    String feePrivateKey = getFeePk(logEntity);
                    //转TRX作为手续费
                    TransactionResult transfer = TrxHelper.transfer(feePrivateKey, userCoin.getAddress(), fee.multiply(BigDecimal.TEN));
                    continue;
                }

                BigDecimal tronBalance = null;

                tronBalance = TrxHelper.getTrxBalance(userCoin.getAddress(), restTemplate);

                if (tronBalance.compareTo(BlConstants.TRX_FEE_MIN.multiply(BlConstants.TRX_DECIMAL)) < 0) {
                    log.info("trx不足,使用手续费地址转手续费: {}", userCoin.getAddress());
                    log.info("TRX转账", userCoin.getAddress());
                    //获取TRX手续费地址
                    String feePrivateKey = getFeePk(logEntity);

                    TransactionResult transfer = TrxHelper.transfer(feePrivateKey, userCoin.getAddress(), fee.multiply(BigDecimal.TEN));
                    log.info("TRX转账成功", transfer.getHash());
                    continue;
                }

                BigInteger usdtBalanceBig = null;

                usdtBalanceBig = Trc20Helper.getTrc20Balance(userCoin.getAddress(), restTemplate).toBigInteger();

                BigDecimal usdtBalance = new BigDecimal(usdtBalanceBig).divide(BlConstants.USDT_DECIMAL, BlConstants.UsdtDecimal, BigDecimal.ROUND_DOWN);

                log.info("归集: {}, 金额: {}", userCoin.getAddress(), usdtBalance);
                TransactionResult transfer = Trc20Helper.transfer(outPrivateKey, inAddress, usdtBalance, contractAddress, fee.multiply(new BigDecimal("10000000")).longValue());

                //更新recharge_log表数据
                logEntity.setState(RechargeLogTypeEnum.COLLECT_SUCCESS.getCode());
                logEntity.setModifyTime(new Date());
                rechargeLogMapperExt.updateByPrimaryKeySelective(logEntity);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                feignService.sendEmail("用户id:" + logEntity.getUserId() + "  公链:" + logEntity.getChainName() + "  币种:" + logEntity.getCoinName()
                        + "  归集目的地址:" + logEntity.getToAddress() + "  异常信息:" + StringUtils.printStackTraceToString(e));
                continue;
            }
        }
    }

    private String getFeePk(RechargeLog logEntity) {
        //获取TRX手续费地址
        UserWalletInfo feeUserWalletInfo = new UserWalletInfo();
        feeUserWalletInfo.setChainName(logEntity.getChainName());
        feeUserWalletInfo.setCoinName(logEntity.getCoinName());
        feeUserWalletInfo.setUserId(AddressTypeEnum.FEE.getCode());
        UserWalletInfo req = userWalletInfoMapperExt.selectOne(feeUserWalletInfo);

        String feePrivateKey = DES3Util.doubleDecode(req.getPrivateKey(), secrectKey, req.getSalt());
        return feePrivateKey;
    }

}
